#ifndef SHARED_PTR_H
#define SHARED_PTR_H

template<typename T> class shared_ptr{
	public:
		shared_ptr<T>(T);
		shared_ptr<T>(const shared_ptr<T> &);
		~shared_ptr<T>();
		shared_ptr<T>& operator=(shared_ptr<T> &);

		T& operator*() const;

	private:
		T	*m_ptr;
		int *m_refNum;

};

template<typename T>
shared_ptr<T>::shared_ptr(T t){
	m_ptr = new T(t);
	m_refNum = new int;
	*m_refNum = 1;
}

template<typename T>
shared_ptr<T>::shared_ptr(const shared_ptr<T> &p)
	: m_ptr(p.m_ptr), m_refNum(p.m_refNum)
{
	(*m_refNum)++;
}

template<typename T>
shared_ptr<T>::~shared_ptr(){
	if(*m_refNum == 1){
		delete m_refNum;
		delete m_ptr;
	}
	(*m_refNum)--;
}

template <typename T>
shared_ptr<T> & shared_ptr<T>::operator=(shared_ptr<T> &p){
	(*(p.m_refNum)) ++;
	(*m_refNum)--;
	if(*m_refNum == 0){
		delete m_refNum;
		delete m_ptr;
	}
	m_refNum = p.m_refNum;
	m_ptr = p.m_ptr;
}

template <typename T>
T& shared_ptr<T>::operator*() const{
	return *m_ptr;
}

template<typename T>
shared_ptr<T> make_shared(T t){
	return shared_ptr<T>(t);
}

#endif /* SHARED_PTR_H */
